/*  Copyright (C) 2008 Davide Andreoli (see AUTHORS)
 *
 *  This file is part of extramenu.
 *  extramenu is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  extramenu is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with extramenu.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
 */
#include <e.h>
#include "e_mod_main.h"
#include "config.h"

static int  _extramenu_new(const char *file);
static void _extramenu_prepare_menu(void *data, E_Menu *em);
static void _extramenu_generate_menu(void *data, E_Menu *em);
static void _extramenu_desktop_run(void *data, E_Menu *m, E_Menu_Item *mi);
static void _extramenu_set_menuitem_icon(const char *icon, E_Menu_Item *mi);
static void _extramenu_parse_dir(const char *dir);
static void _extramenu_monitor_cb(void *data, Ecore_File_Monitor *em, Ecore_File_Event event, const char *path);

Eina_List *menus;
Ecore_File_Monitor *mon1, *mon2;

/***************************************************************************/
/**/
/* module setup */
EAPI E_Module_Api e_modapi =
{
   E_MODULE_API_VERSION,
   "Extra Menu"
};


EAPI void *
e_modapi_init(E_Module *m)
{
   char dir[PATH_MAX];

   /* search in user dir */
   snprintf(dir, PATH_MAX, "%s/"MENU_USER_DIR, e_user_homedir_get());
   _extramenu_parse_dir(dir);
   mon1 = ecore_file_monitor_add(dir, _extramenu_monitor_cb, NULL);

   /* search in system dir */
   _extramenu_parse_dir(MENU_SYSTEM_DIR);
   mon2 = ecore_file_monitor_add(MENU_SYSTEM_DIR, _extramenu_monitor_cb, NULL);

   return m;
}

EAPI int
e_modapi_shutdown(E_Module *m)
{
   if (mon1) ecore_file_monitor_del(mon1);
   if (mon2) ecore_file_monitor_del(mon2);
   while (menus)
   {
      Extra_Menu *menu;

      menu = menus->data;

      e_int_menus_menu_augmentation_del(menu->menu, menu->maug);
      efreet_menu_free(menu->efreet_menu);
      if (menu->menu) eina_stringshare_del(menu->menu);

      free (menu);
      menus = eina_list_remove_list(menus, menus);
   }

   return 1;
}

EAPI int
e_modapi_save(E_Module *m)
{
   return 1;
}

/***************************************************************************/
static void
_extramenu_parse_dir(const char *dir)
{
   Eina_List *files;
   char *filename;
   char buf[PATH_MAX];
   
   /* search in dir */
   files = ecore_file_ls(dir);
   EINA_LIST_FREE(files, filename)
   {
      printf("FILE: %s\n", filename);
      snprintf(buf, PATH_MAX, "%s/%s", dir, filename);
      _extramenu_new(buf);
      free(filename);
   }
}

static int
_extramenu_new(const char *file)
{
   Efreet_Menu *efreet_menu;
   Extra_Menu *menu;
   char *placement = NULL;

   efreet_menu = efreet_menu_parse(file);
   if (!efreet_menu || !efreet_menu->name) return 0;

   menu = E_NEW(Extra_Menu, 1);
   if (!menu) return 0;

   if (efreet_menu->desktop && efreet_menu->desktop->x)
      placement = eina_hash_find(efreet_menu->desktop->x, "X-Enlightenment-Menu");
   if (!placement) placement = DEFAULT_MENU_PLACEMENT;

   menu->menu = eina_stringshare_add(placement);
   menu->maug = e_int_menus_menu_augmentation_add(placement,
                                                  _extramenu_prepare_menu,
                                                  efreet_menu,
                                                  NULL, NULL);
   menu->efreet_menu = efreet_menu;
   menus = eina_list_append(menus, menu);
   return 1;
}

static void
_extramenu_prepare_menu(void *data, E_Menu *em)
{
   Efreet_Menu *menu = data;
   E_Menu_Item *mi;
   E_Menu *m;

   if (!menu || !em) return;

   //printf("**PREPARE MENU: %s\n", menu->name);

   mi = e_menu_item_new(em);
   e_menu_item_label_set(mi, menu->name);
   _extramenu_set_menuitem_icon(menu->icon, mi);//CHECK ICON

   m = e_menu_new();
   e_menu_item_submenu_set(mi, m);

   e_menu_pre_activate_callback_set(m, _extramenu_generate_menu, menu);
}

static void
_extramenu_generate_menu(void *data, E_Menu *em)
{
   Efreet_Menu *menu = data;
   E_Menu_Item *mi;
   Efreet_Menu *sub;
   Eina_List *l;

   //printf("**GENERATE MENU: %s (type: %d size: %d)\n", menu->name, menu->type, ecore_list_count(menu->entries));
   
   EINA_LIST_FOREACH(menu->entries, l, sub)
   {
      switch (sub->type)
      {
         case EFREET_MENU_ENTRY_MENU:
            _extramenu_prepare_menu(sub, em);
            break;
         case EFREET_MENU_ENTRY_DESKTOP:
            mi = e_menu_item_new(em);
            e_menu_item_label_set(mi, sub->desktop->name);
            _extramenu_set_menuitem_icon(sub->desktop->icon, mi);
            e_menu_item_callback_set(mi, _extramenu_desktop_run, sub->desktop);
            break;
         case EFREET_MENU_ENTRY_SEPARATOR:
            mi = e_menu_item_new(em);
            e_menu_item_separator_set(mi, 1);
            break;
         default:
            break;
      }
   }
   e_menu_pre_activate_callback_set(em, NULL, NULL);
}

static void
_extramenu_desktop_run(void *data, E_Menu *m, E_Menu_Item *mi)
{
   e_exec(m->zone, (Efreet_Desktop *)data, NULL, NULL, "menu/apps");
}

static void
_extramenu_set_menuitem_icon(const char *icon, E_Menu_Item *mi)
{
   const char *file = NULL;

   if (!icon || !mi) return;

   if (icon[0] == '/')
      e_menu_item_icon_file_set(mi, icon);
   else
   {
      file = efreet_icon_path_find(e_config->icon_theme, icon, 24);
      if (file)
         e_menu_item_icon_file_set(mi, file);
   }
}
static void
_extramenu_monitor_cb(void *data, Ecore_File_Monitor *em, Ecore_File_Event event, const char *path)
{
   //TODO check path extension now
   switch (event)
   {
      case ECORE_FILE_EVENT_NONE:
         printf("MONITOR: None [%s]\n", path);
         break;
      case ECORE_FILE_EVENT_CREATED_FILE:
         printf("MONITOR: created file [%s]\n", path);
         break;
      case ECORE_FILE_EVENT_CREATED_DIRECTORY:
         printf("MONITOR: created directory [%s]\n", path);
         break;
      case ECORE_FILE_EVENT_DELETED_FILE:
         printf("MONITOR: deleted file [%s]\n", path);
         break;
      case ECORE_FILE_EVENT_DELETED_DIRECTORY:
         printf("MONITOR: deleted directory [%s]\n", path);
         break;
      case ECORE_FILE_EVENT_DELETED_SELF:
         printf("MONITOR: deleted self [%s]\n", path);
         break;
      case ECORE_FILE_EVENT_MODIFIED:
         printf("MONITOR: modified [%s]\n", path);
         break;
      default:
         break;
   }
   
   /* destroy all menus */
   while (menus)
   {
      Extra_Menu *menu;

      menu = menus->data;

      e_int_menus_menu_augmentation_del(menu->menu, menu->maug);
      efreet_menu_free(menu->efreet_menu);
      if (menu->menu) eina_stringshare_del(menu->menu);

      free (menu);
      menus = eina_list_remove_list(menus, menus);
   }
   
   
   /* recreate all menus*/
   char dir[PATH_MAX];
   // in user dir
   snprintf(dir, PATH_MAX, "%s/"MENU_USER_DIR, e_user_homedir_get());
   _extramenu_parse_dir(dir);
   //mon1 = ecore_file_monitor_add(dir, _extramenu_monitor_cb, NULL);

   // in system dir */
   _extramenu_parse_dir(MENU_SYSTEM_DIR);
   //mon2 = ecore_file_monitor_add(MENU_SYSTEM_DIR, _extramenu_monitor_cb, NULL);
   
}


